<?php

class Category
{
  /** @var integer */
  public $id;
  /** @var string */
  public $name;
  /** @var string */
  public $title;
  /** @var integer */
  public $status;


  public static $STATUS_PRIVATE = 0;
  public static $STATUS_PUBLIC = 1;

  public static $COLUMN_MAPPING = array(
    'id' => 'id',
    'name' => 'name',
    'title' => 'title',
    'status' => 'status',
  );


  public function __construct($id = null, $name = null)
  {
    $this->Init();

    if (!$this->Load($id, $name))
      $this->Init();
  }

  private function Init()
  {
    $this->id = -1;
  }
  
  private function Load($id = null, $name = null)
  {
    if (!$this->LoadData($id, $name)) return false;
    return true;
  }
  
  private function LoadData($id = null, $name = null)
  {
    $where = 1;

    if (is_numeric($id))
      $where .= " AND id='" . $id . "'";
    else if(is_string($name) && $name != "")
      $where .= " AND name='" . $name . "'";
    // dont load anything if no $id or $name
    else
      return false; 

    $query = "SELECT c.* "
            ." FROM categories AS c"
            ." WHERE $where";

    $rows = DB::query($query);

    // return false if nothing loaded
    if (count($rows) != 1) return false;

    $data = $rows[0];
    $this->SetPropertyValues((array)$data);

    return true;
  }

  /**
   * Populates basic Category properties from a given array of data extracted
   * from the database.
   * @param array $data - dictionary of (<table column name> => <value>)
   */
  private function SetPropertyValues($data)
  {
    $this->id = $data['id'];
    $this->name = $data['name'];
    $this->title = $data["title"];
    $this->status = intval($data['status']);
  }

  /**
   * Saves or adds a new Category to DB
   * Note: $this->title is ignored, set $this->titleRO or titleRU instead.
   */
  public function Save()
  {

    $values = array();
    
    $values['name'] = $this->name;
    // double-check that name is valid
    if (!Category::ValidateName($this->name) || !Category::CheckNameUniqueness($this->name, $this->id))
      return false;

    $values['status'] = intval($this->status);
    $values['title'] = $this->title;
    $values['name'] = $this->Name;


    $oldCategory = new Category($this->id);



    // generate table name and update item tables recursively
    $this->SaveOrUpdateTableName($oldCategory, true);

    // generate url path and save it recursively
    $this->SaveOrUpdateUrlPath($oldCategory);
    
    return $res;
  }
  
  public function Delete()
  {
    if ($this->id == -1) return false;
    
    // set successful return
    $res = true;
    $res = DeleteRow('categories', "id={$this->id}") && $res;
    return $res;
  }

  /**
   * Loads categories from database.
   * @param whereCondition - additional SQL WHERE conditional
   * @param joinedTables - additional SQL JOIN predicate
   * @param querySuffix - additional SQL query suffix
   *
   * @return <Array<Category>> $categories - categories
   */
  public static function &LoadCategories($where = null, $join = null, $suffix = null, $columns = null)
  {
    $categories = array();

    $query = "SELECT DISTINCT c.* $columns"
            ." FROM categories AS c $join"
            ." WHERE 1 $where $suffix";

    $rows = DB::query($query);
    for ($i = 0, $count = count($rows); $i < $count; $i++)
    {
      $category = new Category();
      $category->SetPropertyValues((array) $rows[$i]);
      $categories[] = $category;
    }
    
    return $categories;
  }

  /**
   * Gets ORDER BY clause from incoming pagination data.
   * @param <Array> $paginationData
   * @return <type>
   */
  public static function BuildOrderByClause(&$paginationData)
  {
    $dir = strtolower($paginationData['dir']) == "asc" ? "asc" : "desc";
    $sort = $paginationData['sort'];
    $fields = Category::$COLUMN_MAPPING;
    $orderClause = "";
    if (array_key_exists($sort, $fields))
    {
      $orderClause = " ORDER BY c.{$fields[$sort]} {$dir}";
    }
    return $orderClause;
  }



  /**
   * Checks if name is word with only [a-zA-Z-] letters
   * @param string $name
   * @return <boolean>
   */
  public static function ValidateName($name)
  {
    return ValidInternalName($name);
  }
  
  /**
   * Checks $column for uniqueness.
   * @param <type> $value - name
   * @param <type> $categoryId - id to ignore
   * @return <type>
   */
  public static function CheckNameUniqueness($value, $categoryId = null)
  {
    $where = "name=" . ToSqlQuotedString($value);
    if (ValidId($categoryId))
      $where .= " AND id<>" . ToSqlQuotedString($categoryId);
    return !RowExists('categories', $where);
  }
  
  /**
   * Checks category's $urlName for uniqueness.
   * @param <type> $value - category name
   * @param <type> $categoryId - category to ignore
   * @return <type>
   */
  public static function CheckUrlNameUniqueness($lang, $value, $parentId = null, $categoryId = null)
  {
    if ($lang == 'ro')
      $field = 'url_name_ro';
    else if ($lang == 'ru')
      $field = 'url_name_ro';
    else
      return false;
    $where = "$field=" . ToSqlQuotedString($value);
    if (ValidId($parentId))
      $where .= " AND parent_id=" . ToSqlQuotedString($parentId);
    else
      $where .= " AND parent_id IS NULL";
    if (ValidId($categoryId))
      $where .= " AND id<>" . ToSqlQuotedString($categoryId);
    return !RowExists('categories', $where);
  }


  /**
   * Returns $filename's full path for given $preset
   * @param String $filepath
   * @param String $preset
   * @return String $fileUri
   */
  public static function GenerateImageUrl($filepath, $preset)
  {
    $filepath = basename($filepath);
    $imagesPath = FILES_CATEGORIES_ICONS_PATH;
    
    if ($preset == IMAGE_PRESET_ORIGINAL)
      $imagesPath = $imagesPath . FOLDER_ORIGINAL;

    global $IMAGE_PRESETS_SHOPS;
    $presets = array();
    foreach ($IMAGE_PRESETS_SHOPS as $presetConst)
    {
      $name = constant($presetConst);
      $suffix = constant($presetConst . "_SUFFIX");
      if ($name && $suffix)
        $presets[$name] = $suffix;
    }
    // force addition of original preset
    $presets[IMAGE_PRESET_ORIGINAL] = IMAGE_PRESET_ORIGINAL_SUFFIX;
    $suffix = $presets[$preset];
    return $imagesPath . str_replace(array_values($presets), $suffix, $filepath);
  }

  /**
   * Generates unique url path of the form "{$parentCategory::url_name}/{$category::url_name}"
   */
  public function GenerateUrlPath()
  {
    $urlPathRO = $this->urlNameRO;
    $urlPathRU = $this->urlNameRU;
    $degree = 0;
    $parent = $this->LoadParentCategory();
    while ($degree < 4 && $parent->id > 0)
    {
      $degree++;
      $urlPathRO = $parent->urlNameRO . "/" . $urlPathRO;
      $urlPathRU = $parent->urlNameRU . "/" . $urlPathRU;
      $parent = $parent->LoadParentCategory();
    }
    $this->urlPathRO = $urlPathRO;
    $this->urlPathRU = $urlPathRU;
  }

}
?>
